Analyze Result

In this example, you learn to use ResultAnalyzer. You has already use it in preivous example to instanciate plotting: agg = hd.ResultAnalyzer(study, result)

Let’s begin by build little study with two nodes (A and B) both has a sinus-like load from 1500 to 500. Node A has a constant nuclear plan, node B has eolien with linear random.

import hadar as hd
import numpy as np
import pandas as pd
t = np.linspace(0, np.pi * 14, 168)
load = 1000 + np.sin(t) * 500
eolien = np.random.rand(t.size) * 1000
study = hd.Study(horizon=t.size, nb_scn=1)\
    .network()\
        .node('a')\
            .consumption(name='load', cost=10 ** 6, quantity=load)\
            .production(name='nuclear', cost=100, quantity=1500)\
        .node('b')\
            .consumption(name='load', cost=10 ** 6, quantity=load)\
            .production(name='eolien', cost=50, quantity=eolien)\
        .link(src='a', dest='b', cost=5, quantity=2000)\
        .link(src='b', dest='a', cost=5, quantity=2000)\
    .build()
opt = hd.LPOptimizer()
res = opt.solve(study)
agg = hd.ResultAnalyzer(study=study, result=res)

Low API

Analyzer provide a low api, that means result could not be ready-to-use, but it’s a very flexible way to analyze data. Low API enable to thinks: - set order. data has for level : node, element, scn and time. Low API can organize for your these level - filtering: for each level you can apply a filter, to only select node ‘a’, or time from 10 to 35 timestep

For examples you want select consumption named load other all node just for 57 to 78 timestep

agg.network().scn(0).consumption('load').node().time(slice(57, 78))
asked cost given
node t
a 57.0 1320.592505 1000000.0 1320.592505
58.0 1209.650140 1000000.0 1209.650140
59.0 1084.249841 1000000.0 1084.249841
60.0 953.039486 1000000.0 953.039486
61.0 825.067633 1000000.0 825.067633
62.0 709.159500 1000000.0 709.159500
63.0 613.308369 1000000.0 613.308369
64.0 544.124344 1000000.0 544.124344
65.0 506.378508 1000000.0 506.378508
66.0 502.673897 1000000.0 502.673897
67.0 533.265990 1000000.0 533.265990
68.0 596.045087 1000000.0 596.045087
69.0 686.681805 1000000.0 686.681805
70.0 798.925635 1000000.0 798.925635
71.0 925.035996 1000000.0 925.035996
72.0 1056.316041 1000000.0 1056.316041
73.0 1183.712406 1000000.0 1183.712406
74.0 1298.439560 1000000.0 1298.439560
75.0 1392.585665 1000000.0 1392.585665
76.0 1459.658198 1000000.0 1459.658198
77.0 1495.031689 1000000.0 1495.031689
b 57.0 1320.592505 1000000.0 790.231774
58.0 1209.650140 1000000.0 351.005132
59.0 1084.249841 1000000.0 485.779325
60.0 953.039486 1000000.0 953.039486
61.0 825.067633 1000000.0 825.067633
62.0 709.159500 1000000.0 709.159500
63.0 613.308369 1000000.0 613.308369
64.0 544.124344 1000000.0 544.124344
65.0 506.378508 1000000.0 506.378508
66.0 502.673897 1000000.0 502.673897
67.0 533.265990 1000000.0 533.265990
68.0 596.045087 1000000.0 596.045087
69.0 686.681805 1000000.0 686.681805
70.0 798.925635 1000000.0 798.925635
71.0 925.035996 1000000.0 925.035996
72.0 1056.316041 1000000.0 933.836811
73.0 1183.712406 1000000.0 1033.211070
74.0 1298.439560 1000000.0 601.396040
75.0 1392.585665 1000000.0 832.053023
76.0 1459.658198 1000000.0 439.140553
77.0 1495.031689 1000000.0 451.215115

TIP If filter return only one element, set it at first. First indexes with one element are removed to avoir useless indexes.

Another example: Analyze all production first 24 timestep

agg.network().scn(0).node().production().time(slice(0,24))
avail cost used
node name t
a nuclear 0.0 1500.000000 100.0 1500.000000
1.0 1500.000000 100.0 1500.000000
2.0 1500.000000 100.0 1500.000000
3.0 1500.000000 100.0 1500.000000
4.0 1500.000000 100.0 1500.000000
5.0 1500.000000 100.0 1500.000000
6.0 1500.000000 100.0 1500.000000
7.0 1500.000000 100.0 1500.000000
8.0 1500.000000 100.0 1500.000000
9.0 1500.000000 100.0 1500.000000
10.0 1500.000000 100.0 1500.000000
11.0 1500.000000 100.0 1500.000000
12.0 1500.000000 100.0 1388.655756
13.0 1500.000000 100.0 1376.698459
14.0 1500.000000 100.0 1157.759171
15.0 1500.000000 100.0 318.599505
16.0 1500.000000 100.0 775.000819
17.0 1500.000000 100.0 937.348977
18.0 1500.000000 100.0 32.439151
19.0 1500.000000 100.0 202.087813
20.0 1500.000000 100.0 806.885534
21.0 1500.000000 100.0 996.520417
22.0 1500.000000 100.0 1264.946884
23.0 1500.000000 100.0 1357.308648
b eolien 0.0 313.568200 50.0 313.568200
1.0 212.562928 50.0 212.562928
2.0 761.045464 50.0 761.045464
3.0 927.244388 50.0 927.244388
4.0 529.827565 50.0 529.827565
5.0 839.655655 50.0 839.655655
6.0 103.955853 50.0 103.955853
7.0 91.087054 50.0 91.087054
8.0 171.107957 50.0 171.107957
9.0 810.780478 50.0 810.780478
10.0 409.857521 50.0 409.857521
11.0 675.910071 50.0 675.910071
12.0 592.533421 50.0 592.533421
13.0 344.852429 50.0 344.852429
14.0 323.355891 50.0 323.355891
15.0 957.863179 50.0 957.863179
16.0 346.706214 50.0 346.706214
17.0 90.171422 50.0 90.171422
18.0 967.958947 50.0 967.958947
19.0 840.122734 50.0 840.122734
20.0 343.188731 50.0 343.188731
21.0 320.030316 50.0 320.030316
22.0 265.212484 50.0 265.212484
23.0 418.860600 50.0 418.860600

To summrize low api, you can organize and filter data by network, scenarios, time, node and elements on node.

High API

High API is ready to use data. It gives you a business oriented data about adequacy. Today we have: - Get balance to compute net position on a node - Get cost to compute cost on a node - Get Remain Available Capacities

import plotly.graph_objects as go
def plot(y):
    return go.Figure(go.Scatter(x=t, y=y.flatten()))
data = agg.get_balance(node='a') # Compute net exchange for all scenario and timestep
plot(data)
data = agg.get_cost(node='b') # Compute cost for all scenario and timestep
plot(data)
data = agg.get_rac() # Compute Remain Available Capacities for all scenarios and timestep
plot(data)